# ***************************************************************************
# *   Copyright (C) 2014 by Edson Borin                                     *
# *   edson@ic.unicamp.br                                                   *
# *                                                                         *
# *   This program is free software; you can redistribute it and/or modify  *
# *   it under the terms of the GNU General Public License as published by  *
# *   the Free Software Foundation; either version 2 of the License, or     *
# *   (at your option) any later version.                                   *
# *                                                                         *
# *   This program is distributed in the hope that it will be useful,       *
# *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
# *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
# *   GNU General Public License for more details.                          *
# *                                                                         *
# *   You should have received a copy of the GNU General Public License     *
# *   along with this program; if not, write to the                         *
# *   Free Software Foundation, Inc.,                                       *
# *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
# ***************************************************************************

import pygame
import sys
import os

# ******************************************
# Helper functions - Verbose messages and fatal
# ******************************************
def verbose_clean(scr) :
    global verbln
    verbln = 0
    backgnd = pygame.Surface(screen.get_size()).convert()
    backgnd.fill((0,0,0))
    scr.blit(backgnd,(0,0))

def verbose(scr,msg) :
    global verbln
    f32 = pygame.font.Font(None, 32)
    font_height = f32.get_height()
    left_margin = 10
    surf_msg = f32.render(msg, 0, (50,50,50))
    scr.blit(surf_msg,(left_margin,verbln))
    verbln = verbln + font_height;
    pygame.display.flip()

# Prints a message and exits with status value
def fatal(status,msg) :
        sys.stderr.write('FATAL: '+msg+'\n')
        sys.exit(status)

# ******************************************
# Load images functions
# ******************************************
def img_to_back(i) :
    back = pygame.Surface(i.get_size())
    back = back.convert()
    back.blit(i,(0,0))
    img_ratio = float(i.get_width()) / float(i.get_height())
    scr_ratio = float(disp_w) / float(disp_h)
    if img_ratio > scr_ratio : 
        # wide image. Scale it to (disp_w, disp_w/img_ratio)
        scale_to = (disp_w, int(float(disp_w)/img_ratio))
    else :
        scale_to = (int(disp_h*img_ratio), disp_h)
    back = pygame.transform.scale(back,scale_to)
    return back

# Returns a list of tuples ("filename.jpg", pygame.image, pygame.back_img)
def read_jpg_files(dirname) :
	fn_lst = os.listdir(dirname)
	fn_lst = sorted(fn_lst)
	img_list = []
	for fn in fn_lst :
		try :
			img = pygame.image.load(os.path.join(dirname,fn))
			back = img_to_back(img)
			img_list.append((fn,img,back))
		except:
			print "Warning could not open file "+fn
	return img_list

# ******************************************
# Fading in/out
# ******************************************
def fade_out(scr,img) :
    backgnd = pygame.Surface(scr.get_size()).convert()
    for i in range(250,-1,-25) :
        backgnd.fill((0,0,0))
        img.set_alpha(i)
        scr.blit(img, (int((disp_w-img.get_width())/2),
		       int((disp_h-img.get_height())/2)))
        pygame.display.flip()
	pygame.time.delay(20)

def fade_in(scr,img) :
    backgnd = pygame.Surface(scr.get_size()).convert()
    for i in range(0, 250, 25) :
        backgnd.fill((0,0,0))
        img.set_alpha(i)
        scr.blit(img, (int((disp_w-img.get_width())/2),
		       int((disp_h-img.get_height())/2)))
        pygame.display.flip()
	pygame.time.delay(20)

# ******************************************
# List rotate operations
# ******************************************
def rotate_left(lst) :
	i = lst.pop(0)
	lst.append(i)

def rotate_right(lst) :
        i = lst.pop();
        lst.insert(0,i)

# ******************************************
# Auto slides next and previous functions
# ******************************************
def auto_list_next(screen) :
	(fn,img,previous) = auto_list[0]
	rotate_left(auto_list)
        (fn,img,current) = auto_list[0]
	fade_out(screen,previous)
	fade_in(screen,current)

def auto_list_previous(screen) :
	(fn,img,previous) = auto_list[0]
	rotate_right(auto_list)
        (fn,img,current) = auto_list[0]
	fade_out(screen,previous)
	fade_in(screen,current)

# ******************************************
#  Main
# ******************************************

# Setup the environment
pygame.init()
pygame.mouse.set_visible(0)

verbln    = 0;
screen    = pygame.display.set_mode((0,0),pygame.FULLSCREEN)
disp_info = pygame.display.Info()
disp_w    = disp_info.current_w
disp_h    = disp_info.current_h 
default_list = []

verbose(screen,"Setting screen mode: ("+str(disp_w)+","+str(disp_h)+")")

# Parser display data
try:
	# parser_display_data()
	verbose(screen,"Reading image files...")
	default_list = read_jpg_files("default-presentation")
	verbose(screen,"Reading image files... [Done]")
except:
	fatal(1,"error when parsing display data. Cannot continue.")
	
# Two kind of data
# a) Free menu navigation data
#    TODO: implement this functionality
# b) Default presentation. 
auto_list = default_list

from time import sleep, time

AUTO_FRAME_DELAY = 15000 # 15s
AUTO_START_DELAY = 20000 # 20s

verbose_clean(screen)

# Add an event to trigger the auto mode
pygame.time.set_timer(pygame.USEREVENT, 3000) # apply force

done = False
while not done:
    event = pygame.event.wait()
    if event.type == pygame.QUIT:
        done = True
    elif event.type == pygame.USEREVENT:
        # Auto mode. Add a new event to trigger next slide after AUTO_FRAME_DELAY
        pygame.time.set_timer(pygame.USEREVENT, AUTO_FRAME_DELAY) 
        auto_list_next(screen)
    elif event.type == pygame.MOUSEBUTTONDOWN:
        #Add a new event to trigger auto mode after AUTO_START_DELAY
        pygame.time.set_timer(pygame.USEREVENT, AUTO_START_DELAY) 
        auto_list_next(screen)
    elif event.type == pygame.KEYDOWN:
        if event.key == pygame.K_ESCAPE:
            done = True
        if event.key == pygame.K_q:
            done = True
        if event.key == pygame.K_p:
            #Reset timer to stop auto mode
            pygame.time.set_timer(pygame.USEREVENT, 0) # Stop auto
        elif event.key == pygame.K_LEFT: 
            #Add a new event to trigger auto mode after AUTO_START_DELAY
            pygame.time.set_timer(pygame.USEREVENT, AUTO_START_DELAY) 
            auto_list_previous(screen)
        elif event.key == pygame.K_RIGHT:
            #Add a new event to trigger auto mode after AUTO_START_DELAY
            pygame.time.set_timer(pygame.USEREVENT, AUTO_START_DELAY) 
            auto_list_next(screen)
            
pygame.quit();
